using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.IO;
using System.Diagnostics;
using System.Text;


namespace ABA
{
    public class ConverConfig
    {
        public static void GenCSharp(List<SettingItem> list)
        {
            if (Directory.Exists(Path_ExcelConfig.ExcelFolder))
            {
                if (!Directory.Exists(Path_ExcelConfig.GenCSharpFolder))
                    Directory.CreateDirectory(Path_ExcelConfig.GenCSharpFolder);

                Stopwatch watch = new Stopwatch();
                watch.Start();
                foreach (var item in list)
                {
                    GenCSharp(item);
                }
                AssetDatabase.Refresh();
                watch.Stop();
                int seconds = (int)watch.ElapsedMilliseconds / 1000;
                EditorUtility.DisplayDialog("提示", $"生成CSharp,耗时{seconds}秒", "好的");
                AssetDatabase.Refresh();
            }
            else
            {
                if (EditorUtility.DisplayDialog("提示", "配表路径有问题，请检查！！", "这就去"))
                {
                    SettingWnd.ShowWindow(Path_ExcelConfig.TAG);
                }
            }
        }

        public static void GenCSharp(SettingItem item)
        {
            if (Directory.Exists(Path_ExcelConfig.ExcelFolder))
            {
                var listData = GetTableData(item);
                for (int i = 0; i < listData.Count; i++)
                {
                    var data = listData[i];
                    string str_csharp = GetCSharpString(data);
                    string path = $"{Path_ExcelConfig.GenCSharpFolder}/Config_{data.tableName}.cs";
                    if (!Directory.Exists(Path_ExcelConfig.GenCSharpFolder))
                        Directory.CreateDirectory(Path_ExcelConfig.GenCSharpFolder);


                    File.WriteAllText(path, str_csharp);  

                    if(data.tableName == "Pf"){
                        GenPfCSharpString(data);
                    }      
                    // if(data.tableName == "Error"){
                    //     GenErrorCSharpString(data);
                    // }                     
                    File.WriteAllText(path, str_csharp);                    
                }
            }
        }

        static string error_template = @"
/*代码自动生成的类，请勿手动修改*/
namespace ABA
{
    public class ErrorConst
    {
        {ITEM_LIST}
    }
}";
        static string error_template_item = @"
        public static int {NAME} = {ERROR};        
";

        private static void GenErrorCSharpString(ExcelData excelData)
        {   
            string str = "";
            for (int i = 0; i < excelData._valueList.Count; i++)
            {
                string[] line = excelData._valueList[i];

                StringBuilder sb = new StringBuilder();
                sb.Append(error_template_item);
                sb.Replace("{NAME}", line[2]);
                sb.Replace("{ERROR}", line[1]);
                str += sb.ToString();
            }

            var builder = new StringBuilder();
            builder.Append(error_template);
            builder.Replace("{ITEM_LIST}", str);
            string result = builder.ToString();
            File.WriteAllText($"{Path_ExcelConfig.GenCSharpFolder}/ErrorConst.cs", result);                        
        }


        static string pf_template = @"
/*代码自动生成的类，请勿手动修改*/

namespace ABA
{
    public class PfInfo{
        public int id; // 唯一
        public int type;
        public string name;
        public string desc;
        public string ip;
        public int    port;
    }

    public class PfConst
    {
        {ITEM_LIST}
    }
}";
        static string pf_template_item = @"
        public static PfInfo {NAME} = new PfInfo{
            id         = {ID},
            type       = {TYPE},
            name       = ""{NAME}"",
            desc       = ""{DESC}"",
            ip         = ""{IP}"",
            port       = {PORT},
        };     
";

        private static void GenPfCSharpString(ExcelData excelData)
        {
            string str = "";
            for (int i = 0; i < excelData._valueList.Count; i++)
            {
                string[] line = excelData._valueList[i];

                StringBuilder sb = new StringBuilder();
                sb.Append(pf_template_item);
                sb.Replace("{NAME}", line[2]);
                sb.Replace("{ID}", line[0]);
                sb.Replace("{TYPE}", line[1]);
                sb.Replace("{DESC}", line[3]);
                sb.Replace("{IP}", line[4]);
                sb.Replace("{PORT}", line[5]);
                str += sb.ToString();
            }

            var builder = new StringBuilder();
            builder.Append(pf_template);
            builder.Replace("{ITEM_LIST}", str);
            string result = builder.ToString();
            File.WriteAllText($"{Path_ExcelConfig.GenCSharpFolder}/PfConst.cs", result);  
        }


        /// <summary>
        /// 获取表格数据
        /// </summary>
        public static List<ExcelData> GetTableData(SettingItem item)
        {
            return GetTableData(item.Name);
        }
        public static List<ExcelData> GetTableData(string itemName)
        {
            var decoder = new DecodeExcel();
            return decoder.Decode($"{Path_ExcelConfig.ExcelFolder}/{itemName}");
        }
        static string GetCSharpString(ExcelData excelData)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < excelData._fieldNameList.Count; i++)
            {
                sb.AppendLine("\t\t/// <summary>");
                sb.Append("\t\t/// " + excelData._fieldNameList[i]);
                if (!string.IsNullOrEmpty(excelData._commentList[i]))
                    sb.AppendFormat("({0})", excelData._commentList[i]);
                sb.AppendLine();
                sb.AppendLine("\t\t/// <summary>");
                sb.Append("\t\tpublic ");
                switch (excelData._typeNameList[i].ToLower())
                {
                    case "byte": sb.Append("short "); break;
                    case "string": sb.Append("string "); break;
                    case "bool": sb.Append("bool "); break;
                    case "int":
                    case "int32": sb.Append("int "); break;
                    case "uint":
                    case "uint32": sb.Append("uint "); break;
                    case "int64":
                    case "long": sb.Append("long "); break;
                    case "datetime": sb.Append("DateTime "); break;
                    case "float": sb.Append("float "); break;
                    case "double": sb.Append("double "); break;


                    case "byte[]": sb.Append("short[] "); break;
                    case "string[]": sb.Append("string[] "); break;
                    case "bool[]": sb.Append("bool[] "); break;
                    case "int[]":
                    case "int32[]": sb.Append("int[] "); break;
                    case "uint[]":
                    case "uint32[]": sb.Append("uint[] "); break;
                    case "int64[]":
                    case "long[]": sb.Append("long[] "); break;
                    case "datetime[]": sb.Append("DateTime[] "); break;
                    case "float[]": sb.Append("float[] "); break;
                    case "double[]": sb.Append("double[] "); break;

                    // TODO:longer Unity ScriptableObject 不能直接存储字典和二维数组 ！！！！！！！
                    // case "byte[,]": sb.Append("short[,] "); break;
                    // case "string[,]": sb.Append("string[,] "); break;
                    // case "bool[,]": sb.Append("bool[,] "); break;
                    // case "int[,]":
                    // case "int32[,]": sb.Append("int[,] "); break;
                    // case "uint[,]":
                    // case "uint32[,]": sb.Append("uint[,] "); break;
                    // case "int64[,]":
                    // case "long[,]": sb.Append("long[,] "); break;
                    // case "datetime[,]": sb.Append("DateTime[,] "); break;

                }


                sb.Append(excelData._fieldNameList[i]);
                sb.AppendLine(";");
            }

            var builder = new StringBuilder();
            builder.Append(String_Config_Template);
            builder.Replace("{FILE_NAME}", excelData.tableName);
            builder.Replace("{ITEM_CLASS_VARIABLE}", sb.ToString());
            builder.Replace("{ASSET_PATH}", Path_ExcelConfig.GenAssetFolder.Replace(Application.dataPath, ""));
            string result = builder.ToString();

            return result;
        }

        /// <summary>
        /// Excel转CSharp脚本模板
        /// </summary>
        public const string String_Config_Template = @"
/// <summary>
/// 本文件中的代码为生成的代码，不允许手动修改
/// Generate by longer
/// </summary>

using System;
using System.Collections.Generic;
using UnityEngine;

namespace ABA
{
    [Serializable]
    public partial class Item_{FILE_NAME}
    {
{ITEM_CLASS_VARIABLE}
    }

    public partial class Config_{FILE_NAME} : ScriptableObject
    {
        private static Config_{FILE_NAME} _instence = null;
        public List<Item_{FILE_NAME}> list; 

        public static Config_{FILE_NAME} inst
        {
            get
            {
                if (_instence == null) Init();
                return _instence;
            }
        }

        public static string CONFIG_NAME = ""Config_{FILE_NAME}"";
        static string ConfPath()
        {
            if (Comm.isEditorNoPlaying)
                return ""Assets/MyAssets/Config/"" + CONFIG_NAME + "".asset"";
            else
                return CONFIG_NAME;
        }

        private static void Init()
        {
            Config_{FILE_NAME} obj;
#if UNITY_EDITOR
            if (Comm.isEditorNoPlaying)
                obj = UnityEditor.AssetDatabase.LoadAssetAtPath<Config_{FILE_NAME}>(ConfPath());
            else
                obj = Asset.inst.GetAssetFromCache<Config_{FILE_NAME}>(ConfPath());

#else
                obj = Asset.inst.GetAssetFromCache<Config_{FILE_NAME}>(ConfPath());
#endif
            _instence = obj;
        }

        public Item_{FILE_NAME} GetItemById(int id)
        {
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].id == id)
                {
                    return list[i];
                }
            }
            return null;
        }
    }
}";


    }
}

